package com.zn.znch.yhp.znchv2.service;


import com.zn.znch.yhp.znchv2.common.DCLinJieDate;
import com.zn.znch.yhp.znchv2.common.DateUtil;
import com.zn.znch.yhp.znchv2.domain.DTO.PointData;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;


@Slf4j
public class DCTask  implements Callable<String> {
    private File directory;
    private String name;
    private String[] params;
    private String sysTime;
    private String fuhe;
    private String biwen;
    private String chuihui;

    public static int FUHE_START = 8;
    public static int FUHE_END = 6;
    public static int NOFUHE_START = 2;
    public static int NOFUHE_END = 1;
    public static int maxLine = 86400;
    public DCTask(File directory, String name, String[] params, String sysTime, String fuhe, String biwen, String chuihui,
                  int FUHE_START,int FUHE_END,int NOFUHE_START,int NOFUHE_END,int maxLine) {
        this.directory = directory;
        this.name = name;
        this.params = params;
        this.sysTime = sysTime;
        this.fuhe = fuhe;
        this.biwen = biwen;
        this.chuihui = chuihui;
        this.FUHE_START = FUHE_START;
        this.FUHE_END = FUHE_END;
        this.NOFUHE_START =NOFUHE_START;
        this.NOFUHE_END = NOFUHE_END;
        this.maxLine = maxLine;
    }

    @Override
    public String call() throws Exception {
        System.out.println("任务开始："+name);
        //如果负荷小于400，则认为是停机状态,则直接返回不需要吹灰
        if(Double.parseDouble(fuhe)<400){
            return name+"_0";
        }
        List<PointData> pointList = readAndWrite(directory, name, params, sysTime, fuhe, biwen, chuihui);
        System.out.println("文件读写成功："+name);
        //判断是否要吹灰：根据配置文件选择不同的方法
        if (pointList.size() <= 20000) {
            log.info("当前{}文件总数据量数据不满足20000不进行吹灰判断", name);
            return name+"_"+"0";
        }
        String mark = params[3];
        double alfa = Double.parseDouble(params[4]);
        boolean flag = false;
        try {
            if ("2".equals(mark)) {
                //拟合效果好
                flag = method2(pointList, params, alfa);
            } else {
                //拟合效果不好
                flag = method1(pointList, alfa);
            }
        } catch (Exception e) {
            log.info("短吹判断是否要吹灰异常：directory:{};  name:{};Exception:{}; ",directory,name,e.getMessage());
        }
        String r = flag?"1":"0";
        return name+"_"+r;

    }
    private static List<PointData> readAndWrite(File directory, String name, String[] params, String sysTime, String fuhe, String biwen, String chuihui){
        String filePath = null;
        List<PointData> pointList = new ArrayList<>();
        try {
            filePath = directory.getAbsolutePath() + "\\" + name + ".csv";
            File file = new File(filePath);
            List<String> data = new ArrayList<>();
            if (file.exists()) {
                //读取历史数据
                FileReader fr = new FileReader(filePath);
                BufferedReader br = new BufferedReader(fr);
                String line = br.readLine();
                while (line != null) {
                    data.add(line);
                    String[] lineStr = line.split(",");
                    PointData pointData = new PointData(lineStr[0], Double.parseDouble(lineStr[1]),
                            Double.parseDouble(lineStr[2]), Integer.valueOf(lineStr[3]), Double.parseDouble(lineStr[4]));
                    pointList.add(pointData);
                    line = br.readLine();
                }
                if (data.size() > maxLine) {
                    data.remove(0);
                }
                //删除原文件
                file.delete();
            }
            FileWriter writer = new FileWriter(filePath);
            for (int i = 0; i < data.size(); i++) {
                writer.append(data.get(i));
                writer.append("\n");
            }
            double biwen0 = new BigDecimal(params[0]).multiply(new BigDecimal(fuhe)).multiply(new BigDecimal(fuhe))
                    .add(new BigDecimal(params[1]).multiply(new BigDecimal(fuhe)))
                    .add(new BigDecimal(params[2])).doubleValue();

            //新增逻辑：拟合效果不好,自动掉渣导致吹灰假象
            String mark = params[3];
            if ("1".equals(mark)) {
                List pointDatas = new ArrayList<PointData>();
                Collections.copy(pointDatas,pointList);
                PointData pointMax = getLastList(pointList);

                if(pointMax.getBiwen()<Double.parseDouble(biwen)){
                    chuihui = "2";
                }
            }else{
                if(biwen0<Double.parseDouble(biwen)){
                    chuihui = "2";
                }
            }
            //新增逻辑：重启机器导致吹灰假象，（倒数第5个数据存在是1天以前的，则设置为吹灰标志设置为2，相当于设置5个吹灰标志）
            PointData point = pointList.get(pointList.size()-6);
            if(DateUtil.isWithinTenMinutes(point.getTime(), sysTime, 60*24)){
                chuihui = "2";
            }
            //2024/11/7新增逻辑：获取最后一组数据，如果存在吹灰标志为2的，则判断：最新数据和最近一条数据做差，取绝对值，若结果＞10，则吹灰信号标记为3（如果已经是1或者2了就不覆盖）
            //2024//11/28修改条件：取最新得前20行，取最大值，然后最大值这一行再往前取20行，取最小值，两个相差大于100，则记为3
            String wencha = "";
            int max = 0;
            double maxValue = 0d;
            boolean falg = true;
            for (int i = 0; i < 20; i++) {
                int index = pointList.size()-1-i;
                PointData  p = pointList.get(index);
                if(p.getChuihui()==3){
                    falg = false;
                }
                if(p.getBiwen()>maxValue){
                    max = index ;
                    maxValue = p.getBiwen();
                }
            }
            double minValue = 99999999d;
            if(max>0){
                for (int i = 0; i < 20; i++) {
                    int index = max-1-i;
                    PointData  p = pointList.get(index);
                    if(p.getChuihui()==3){
                        falg = false;
                    }
                    if(p.getBiwen()<minValue){
                        minValue = p.getBiwen();
                    }
                }
            }
            wencha = (maxValue - minValue)+"";
            double linjie = DCLinJieDate.DC_LJZ.get(name);
            //临界值暂时设为100
            linjie = 100d;
            if(maxValue-minValue>linjie &&falg){
                chuihui = "3";
            }

            String lineString = sysTime + "," + fuhe + "," + biwen + "," + chuihui + "," + biwen0 +","+wencha+ "\n";
            writer.append(lineString);
            writer.close();
        } catch (Exception e) {
            log.error("短吹文件处理失败：directory：{}，name：{}，sysTime：{}。错误信息：{}",directory,name,sysTime,e.getMessage());
        }
        log.info(filePath + ":数据更新完成！！");
        return pointList;
    }

    //拟合效果不好
    private static boolean method1(List<PointData> pointList, double alfa) {
//        String lineString = "";
        double biwenMax = pointList.stream().max(Comparator.comparingDouble(PointData::getBiwen)).get().getBiwen();
        double biwenMin = pointList.stream().min(Comparator.comparingDouble(PointData::getBiwen)).get().getBiwen();
        double dt = (biwenMax - biwenMin) / alfa;

        //获取最后一组数据
        PointData pointMax = getLastList(pointList);
        int start = pointMax.getIndex();
        //获取最后一次吹灰后的数据
        pointList = pointList.subList(start, pointList.size());
        //判断最后一个点是否距离上次吹灰10分钟以内或者温度>最大温度，是则直接返回不需要吹灰
        PointData lastPoint = pointList.get(pointList.size() - 1);
        PointData startPoint = pointList.get(0);
        if (lastPoint.getChuihui() == 1 || lastPoint.getChuihui() == 2 || lastPoint.getChuihui() == 3 || lastPoint.getBiwen() > pointMax.getBiwen() || !DateUtil.isWithinTenMinutes(startPoint.getTime(), lastPoint.getTime(), 10)) {
            return false;
        }
        if (pointList.size() <= 30) {
            return false;
        }

        int count = 0;
        for (int i = 0; i < pointList.size(); ) {
            //这里只需要判断最后一组数据
            //短吹后第一个点
            PointData pointData = pointList.get(i);
            double cha = pointMax.getBiwen() - pointData.getBiwen();

            if (cha > dt) {
                //找到下一个pointMax-pointData<0.7dt的点或者超出列表
                Boolean flag = true;
                while (flag) {
                    i++;
                    if (i >= pointList.size()) {
                        return count >= 1;
                    }
                    PointData pointDataNext1 = pointList.get(i);
                    double cha1 = pointMax.getBiwen() - pointDataNext1.getBiwen();
                    if (cha1 < 0.7 * dt) {
                        //满足8小时以上，吹灰+1
                        boolean f8 = DateUtil.isWithinTenMinutes(pointData.getTime(), pointDataNext1.getTime(), 60 * FUHE_START);
                        if (f8) {
//                            lineString = "当前数据点：[" + JSONObject.toJSONString(pointDataNext1) + "]" + "\n";
                            count++;
                            flag = false;
                        } else {
                            //不满足8小时，则判断是否满足6小时以上
                            boolean f6 = DateUtil.isWithinTenMinutes(pointData.getTime(), pointDataNext1.getTime(), 60 * FUHE_END);
                            //找到下一个pointMax-pointData<0.5dt的点或者超出列表
                            if (f6) {
                                boolean flag2 = true;
                                while (flag2) {
                                    i++;
                                    if (i >= pointList.size()) {
                                        return count >= 1;
                                    }
                                    PointData pointDataNext2 = pointList.get(i);
                                    double cha2 = pointMax.getBiwen() - pointDataNext2.getBiwen();
                                    if (cha2 < 0.5 * dt) {
//                                        lineString = "当前数据点：[" + JSONObject.toJSONString(pointDataNext2) + "]" + "\n";
                                        count++;
                                        return count >= 1;
                                    }
                                }
                            } else {
                                i++;
                                flag = false;
                            }
                        }
                    }
                    if (i >= pointList.size()) {
                        return count >= 1;
                    }
                }
            } else {
                i++;
            }
        }
//        //记录吹灰记录
//        if (count >= 1) {
//            try {
//                String path = "D:\\temp\\znch\\cc\\chuihui.txt";
//                File File = new File(path);
//                List<String> list = new ArrayList<>();
//                if (File.exists()) {
//                    FileReader fr = new FileReader(path);
//                    BufferedReader br = new BufferedReader(fr);
//                    String line = br.readLine();
//                    while (line != null) {
//                        list.add(line);
//                        line = br.readLine();
//                    }
//                }
//                FileWriter writer = new FileWriter("D:\\temp\\znch\\cc\\chuihui.txt");
//                for (int i = 0; i < list.size(); i++) {
//                    writer.append(list.get(i));
//                    writer.append("\n");
//                }
//                writer.append(lineString);
//                writer.close();
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
        return count >= 1;
    }

    private static PointData getLastList(List<PointData> pointList){
        //最后一组的最大值
        List<PointData> maxPointList = new ArrayList<>();
        for (int i = 0; i < pointList.size() - 1; i++) {
            PointData point = pointList.get(i);
            PointData next = pointList.get(i + 1);
            PointData pointMax = new PointData();
            if ((point.getChuihui() == 1 || point.getChuihui() == 2 || point.getChuihui() == 3) && next.getChuihui() == 0) {
//                //获取接下来10分钟壁温最高的点
//                while (next.getChuihui() != 1 && !DateUtil.isWithinTenMinutes(startTime, next.getTime(), 10)) {
//                    if (maxPoint.getBiwen() <= next.getBiwen()) {
//                        maxPoint = next;
//                        pointMax = maxPoint;
//                    }
//                    i++;
//                    if(i==pointList.size()-1){
//                        break;
//                    }
//                    next = pointList.get(i + 1);
//                }
                //获取接下去30行最大的温度
                int j = 0;
                for (; j < 30; j++) {
                    if (i + j == pointList.size() - 1) {
                        break;
                    }
                    if (next.getChuihui() != 1 && next.getChuihui() != 2 && pointMax.getBiwen() <= next.getBiwen()) {
                        pointMax = next;
                    }
                    next = pointList.get(j + i);
                }
                maxPointList.add(pointMax);
                pointMax.setIndex(i);
                i = i + j;
            }
        }
        PointData last = maxPointList.get(maxPointList.size()-1);
        return last;
    }

    private static boolean method2(List<PointData> pointList, String[] param, double alfa) {
//        String lineString = "";
        List<PointData> filterList = pointList.stream()
                .filter(point -> point.getFuhe() >= 1900 && point.getFuhe() < 2000).collect(Collectors.toList());
        double biwenMax = filterList.stream().max(Comparator.comparingDouble(PointData::getBiwen)).get().getBiwen();
        double biwenMin = filterList.stream().min(Comparator.comparingDouble(PointData::getBiwen)).get().getBiwen();
        double dt = (biwenMax - biwenMin) * alfa;


        double param1 = new BigDecimal(param[0]).doubleValue();
        double param2 = new BigDecimal(param[1]).doubleValue();
        double param3 = new BigDecimal(param[2]).doubleValue();

        int start = 0;
        for (int i = 0; i < pointList.size() - 1; i++) {
            PointData maxPoint = pointList.get(i);
            PointData next = pointList.get(i + 1);
            if ((maxPoint.getChuihui() == 1 || maxPoint.getChuihui() == 2 || maxPoint.getChuihui() == 3) && next.getChuihui() == 0) {
                start = i;
            }
        }
        //获取最后一次吹灰后的数据
        pointList = pointList.subList(start, pointList.size());
        //判断最后一个点是否距离上次吹灰10分钟以内或者温度>最大温度，是则直接返回不需要吹灰
        PointData lastPoint = pointList.get(pointList.size() - 1);
        PointData startPoint = pointList.get(0);
        if (lastPoint.getChuihui() == 1 ||lastPoint.getChuihui() == 2 ||lastPoint.getChuihui() == 3 ||
                lastPoint.getBiwen() > lastPoint.getBiwenyuche() || !DateUtil.isWithinTenMinutes(startPoint.getTime(), lastPoint.getTime(), 10)) {
            return false;
        }


        int count = 0;
        for (int i = 0; i < pointList.size(); ) {
            PointData pointData = pointList.get(i);
            double x = pointData.getFuhe();
            //计算理论最大温度

            double maxT = x * x * param1 + x * param2 + param3;
            double cha = maxT - pointData.getBiwen();
            if (cha > dt) {
                //找到下一个pointMax-pointData<0.7dt的点或者超出列表
                Boolean flag = true;
                while (flag) {
                    i++;
                    if (i >= pointList.size()) {
                       return count >= 1;
                    }
                    PointData pointDataNext1 = pointList.get(i);
                    double x1 = pointDataNext1.getFuhe();
                    maxT = x1 * x1 * param1 + x1 * param2 + param3;
                    double cha1 = maxT - pointDataNext1.getBiwen();
                    if (cha1 < 0.7 * dt) {
                        //满足8小时以上，吹灰+1
                        boolean f8 = DateUtil.isWithinTenMinutes(pointData.getTime(), pointDataNext1.getTime(), 60 * NOFUHE_START);
                        if (f8) {
//                            lineString = "当前数据点：[" + JSONObject.toJSONString(pointDataNext1) + "]" + "\n";
                            count++;
                            flag = false;
                        } else {
                            //不满足8小时，则判断是否满足6小时以上
                            boolean f6 = DateUtil.isWithinTenMinutes(pointData.getTime(), pointDataNext1.getTime(), 60 * NOFUHE_END);
                            //找到下一个pointMax-pointData<0.5dt的点或者超出列表
                            if (f6) {
                                boolean flag2 = true;
                                while (flag2) {
                                    i++;
                                    if (i >= pointList.size()) {
                                        return count >= 1;
                                    }
                                    PointData pointDataNext2 = pointList.get(i);
                                    double x2 = pointDataNext2.getFuhe();
                                    maxT = x2 * x2 * param1 + x2 * param2 + param3;
                                    double cha2 = maxT - pointDataNext2.getBiwen();
                                    if (cha2 < 0.5 * dt) {
//                                        lineString = "当前数据点：[" + JSONObject.toJSONString(pointDataNext2) + "]" + "\n";
                                        count++;
                                        flag = false;
                                        flag2 = false;
                                    }
                                }
                            } else {
                                i++;
                                flag = false;
                            }
                        }
                    }
                    if (i >= pointList.size() - 1) {
                        return count >= 1;
                    }
                }
            } else {
                i++;
            }
        }

//        //记录吹灰记录
//        if (count >= 1) {
//            try {
//                String path = "D:\\temp\\znch\\dc\\chuihui.txt";
//                File File = new File(path);
//                List<String> list = new ArrayList<>();
//                if (File.exists()) {
//                    FileReader fr = new FileReader(path);
//                    BufferedReader br = new BufferedReader(fr);
//                    String line = br.readLine();
//                    while (line != null) {
//                        list.add(line);
//                        line = br.readLine();
//                    }
//                }
//                FileWriter writer = new FileWriter("D:\\temp\\znch\\dc\\chuihui.txt");
//                for (int i = 0; i < list.size(); i++) {
//                    writer.append(list.get(i));
//                    writer.append("\\n");
//                }
//                writer.append(lineString);
//                writer.close();
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
        return count >= 1;

    }

}
